package root.service.impl;

import com.dtflys.forest.Forest;
import common.CommandTypeEnum;
import common.FileDownloader;
import common.MonitorTcpDataPackage;
import common.UpgradeEntity;
import root.service.CommandHandler;
import root.service.DaemonFunctionService;
import root.service.MonitorSocketConnection;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.function.Consumer;

public class DaemonFunctionServiceImpl implements DaemonFunctionService {

    private static DaemonFunctionServiceImpl daemonFunctionService;
    private final CommandHandler commandHandler;
    private final MonitorSocketConnection monitorSocketConnection= MonitorSocketConnection.getInstance();

    private DaemonFunctionServiceImpl(){
        commandHandler=CommandHandler.getInstance();
    }

    public static DaemonFunctionServiceImpl getInstance() {
        if (daemonFunctionService==null) {
            synchronized (DaemonFunctionServiceImpl.class){
                daemonFunctionService=new DaemonFunctionServiceImpl();
            }
        }
        return daemonFunctionService;
    }
    @Override
    public void runJar() {

    }

    @Override
    public void runMonitorJar(String monitorJarPath, Consumer<String> callback) {
        commandHandler.execCommand(new String[]{System.getProperty("java","java"),"-jar",monitorJarPath},null);
        callback.accept("已执行，PID="+getMonitorPID());
//        if (callback!=null){
//            try {
//                callback.accept(String.valueOf(process.waitFor()));
//            } catch (InterruptedException e) {
//                throw new RuntimeException(e);
//            }
//        }
//        try {
//            var reader = new BufferedReader(new InputStreamReader(process.getInputStream(),"GB18030"));
//            String line;
//            var fullPrint = new StringBuilder();
//            while ((line = reader.readLine()) != null) {
//                fullPrint.append(line).append('\n');
//            }
//            reader.close();
//            callback.accept(fullPrint.toString().strip());
//        } catch (IOException e) {
//            System.err.println(e.getMessage());
//            e.printStackTrace();
//        }

    }

    @Override
    public void ping() {
        var monitorTcpDataPackage=new MonitorTcpDataPackage();
        monitorTcpDataPackage.setCommandTypeEnum(CommandTypeEnum.PING);
        monitorSocketConnection.sendData(monitorTcpDataPackage,resultPackage -> {
            if (CommandTypeEnum.PONG.equals(resultPackage.getCommandTypeEnum()))
                System.out.println("PONG");
            else System.err.println("与monitor断开连接");
        });
    }

    @Override
    public UpgradeEntity checkUpgrade() {
        UpgradeEntity upgradeEntity=null;
        try{
            upgradeEntity=Forest.get(System.getProperty("api")+"/file/upgrade.json").execute(UpgradeEntity.class);
        }catch (Exception e){
            e.printStackTrace();
        }
        return upgradeEntity;
    }

    @Override
    public void getLanNeighbor() {

    }

    @Override
    public int getMonitorPID() {
        var process=commandHandler.execCommand(new String[]{"jps"});
        int pid=-1;
        try {
            var reader = new BufferedReader(new InputStreamReader(process.getInputStream(),"GB18030"));
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.contains("monitor-main")){
                    pid=Integer.parseInt(line.split(" ")[0]);
                    break;
                }
            }
            reader.close();
        } catch (IOException e) {
            System.err.println("获取Monitor PID失败："+e.getMessage());
            e.printStackTrace();
        }
        return pid;
    }

    @Override
    public void killMonitorProcess() {
        int pid=getMonitorPID();
        if (pid==-1)return;
        commandHandler.execCommand(new String[]{"taskkill","/f","/pid", String.valueOf(pid)},null, System.out::println);
    }

    @Override
    public boolean isMonitorRunning() {
        return getMonitorPID()!=-1;
    }

    @Override
    public void sendStringMsg(String message) {
        var monitorTcpDataPackage=new MonitorTcpDataPackage();
        monitorTcpDataPackage.setStringData(message);
        monitorTcpDataPackage.setCommandTypeEnum(CommandTypeEnum.STRING);
        monitorSocketConnection.sendData(monitorTcpDataPackage,resultPackage -> {
            if (CommandTypeEnum.RESPONDED.equals(resultPackage.getCommandTypeEnum()))
                System.out.println("消息成功发送："+message);
            else System.err.println("服务的未正确返回数据："+resultPackage.getCommandTypeEnum());
        });
    }

    @Override
    public void severPing() {
        Forest.get(System.getProperty("api")+"/ping").async().execute();
    }

    @Override
    public int getMonitorVersionCode() {
        var monitorTcpDataPackage=new MonitorTcpDataPackage();
        monitorTcpDataPackage.setCommandTypeEnum(CommandTypeEnum.VERSION_CODE);
        var resultPackage=monitorSocketConnection.getDataPackage(monitorTcpDataPackage);
        return Math.toIntExact(resultPackage != null ? resultPackage.getNumberData() : -1);
    }

    @Override
    public int deleteMonitorJar() {
        var jarFile=new File(System.getProperty("monitor-jar-path"));
        jarFile.deleteOnExit();
        return 1;
    }

    @Override
    public boolean downloadLastMonitorJar() {
        var upgradeEntity=daemonFunctionService.checkUpgrade();
        if (upgradeEntity==null||upgradeEntity.getDownloadUrl()==null||!upgradeEntity.getDownloadUrl().endsWith(".jar")){
            System.err.printf("下载链接错误：%s",upgradeEntity!=null?upgradeEntity.getDownloadUrl():"null");
            return false;
        }
        return FileDownloader.downloadFile(upgradeEntity.getDownloadUrl(),System.getProperty("monitor-jar-path"));
    }

    @Override
    public boolean terminate() {
        String isTerminate="";
        try{
            isTerminate=Forest.get(System.getProperty("api")+"/file/terminate.txt").execute(String.class);
        }catch (Exception e){
            e.printStackTrace();
        }
        return "true".equalsIgnoreCase(isTerminate);
    }
}
